package com.css.openapi.config;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.css.common.core.exception.ServiceException;
import com.css.common.core.utils.BaseUtil;
import feign.FeignException;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import feign.Response;
import feign.codec.DecodeException;
import feign.codec.Decoder;
import feign.codec.Encoder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * @description: 银联商务银行卡相关的feign配置
 * @Title: YlswYhkFeignConfig
 * @Author zhuowugong
 * @Package com.invoice.config
 * @Date 2024/8/17 15:37
 */
@Slf4j
public class ZfjkpPtFeignConfig {

    @Value("${zfjkppt.appid}")
    private String appId;

    @Value("${zfjkppt.appkey}")
    private String appKey;

    private static final String NONCE = "nonce";

    @Bean
    public RequestInterceptor interceptor() {
        return requestTemplate -> {
            log.info("调用支付即开票平台appId:{}", appId);
            String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
            try {
                String body = JSONUtil.toJsonStr(StrUtil.str(requestTemplate.body(), CharsetUtil.UTF_8));
                String authorizationStr = getAuthorization(appId, appKey, timestamp, NONCE, body);
                log.info("调用支付即开票平台参数：{},authorization:{}", body, authorizationStr);
                requestTemplate.header("authorization", authorizationStr);
            } catch (Exception e) {
                log.info("调用支付即开票平台拼接header异常：{}", BaseUtil.getExceptionInfo(e));
                throw new ServiceException("调用支付即开票拼接header异常!");
            }
        };
    }

    @Bean
    public Decoder decoder() {
        return new Decoder() {
            @Override
            public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException {
                String content = IoUtil.read(response.body().asInputStream(), io.netty.util.CharsetUtil.UTF_8);
                com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(content);
                log.info("调用支付即开票平台出参：{}",JSON.toJSONString(jsonObject));
                if(jsonObject.get("data") instanceof com.alibaba.fastjson.JSONObject){
                    JSONObject data = jsonObject.getJSONObject("data");
                    jsonObject.remove("data");
                    if(CollectionUtil.isNotEmpty(data)) {
                        jsonObject.putAll(data);
                    }
                }
                return jsonObject.toJavaObject(type);
            }
        };
    }

    public String getAuthorization(String appid, String appkey, String timestamp, String nonce, String body) throws Exception {
        byte[] data = body.getBytes(StandardCharsets.UTF_8);
        InputStream is = new ByteArrayInputStream(data);
        String testSH = DigestUtils.sha256Hex(is);
        String s1 = appid + timestamp + nonce + testSH;
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(appkey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] localSignature = mac.doFinal(s1.getBytes(StandardCharsets.UTF_8));
        String localSignatureStr = Base64.encodeBase64String(localSignature);
        return "OPEN-BODY-SIG AppId=" + "\"" + appid + "\"" + ", Timestamp=" + "\"" + timestamp + "\"" + ", Nonce="
                + "\"" + nonce + "\"" + ", Signature=" + "\"" + localSignatureStr + "\"";
    }

}
